#ifndef _WX_MIMETYPE_H_
#define _WX_MIMETYPE_H_

// ----------------------------------------------------------------------------
// headers and such
// ----------------------------------------------------------------------------

#include "wx/defs.h"

#if wxUSE_MIMETYPE

// the things we really need
#include "wx/string.h"
#include "wx/dynarray.h"
#include "wx/arrstr.h"

// fwd decls
class wxIconLocation;
class wxFileTypeImpl;
class wxMimeTypesManagerImpl;

// these constants define the MIME informations source under UNIX and are used
// by wxMimeTypesManager::Initialize()
enum wxMailcapStyle {
  wxMAILCAP_STANDARD = 1,
  wxMAILCAP_NETSCAPE = 2,
  wxMAILCAP_KDE = 4,
  wxMAILCAP_GNOME = 8,

  wxMAILCAP_ALL = 15
};

class wxMimeTypeCommands {
  public:
    wxMimeTypeCommands() {}

    wxMimeTypeCommands( const wxArrayString& verbs,
                        const wxArrayString& commands )
      : m_verbs( verbs ),
        m_commands( commands ) {
    }

    // add a new verb with the command or replace the old value
    void AddOrReplaceVerb( const wxString& verb, const wxString& cmd );
    void Add( const wxString& s ) {
      m_verbs.Add( s.BeforeFirst( wxT( '=' ) ) );
      m_commands.Add( s.AfterFirst( wxT( '=' ) ) );
    }

    // access the commands
    size_t GetCount() const { return m_verbs.GetCount(); }
    const wxString& GetVerb( size_t n ) const { return m_verbs[n]; }
    const wxString& GetCmd( size_t n ) const { return m_commands[n]; }

    bool HasVerb( const wxString& verb ) const
    { return m_verbs.Index( verb ) != wxNOT_FOUND; }

    // returns empty string and wxNOT_FOUND in idx if no such verb
    wxString GetCommandForVerb( const wxString& verb, size_t *idx = NULL ) const;

    // get a "verb=command" string
    wxString GetVerbCmd( size_t n ) const;

  private:
    wxArrayString m_verbs;
    wxArrayString m_commands;
};

// ----------------------------------------------------------------------------
// wxFileTypeInfo: static container of information accessed via wxFileType.
//
// This class is used with wxMimeTypesManager::AddFallbacks() and Associate()
// ----------------------------------------------------------------------------

class wxFileTypeInfo {
  public:
    // ctors
    // a normal item
    wxFileTypeInfo( const wxChar *mimeType,
                    const wxChar *openCmd,
                    const wxChar *printCmd,
                    const wxChar *desc,
                    // the other parameters form a NULL terminated list of
                    // extensions
                    ... );

    // the array elements correspond to the parameters of the ctor above in
    // the same order
    wxFileTypeInfo( const wxArrayString& sArray );

    // invalid item - use this to terminate the array passed to
    // wxMimeTypesManager::AddFallbacks
    wxFileTypeInfo() { }

    // test if this object can be used
    bool IsValid() const { return !m_mimeType.empty(); }

    // setters
    // set the icon info
    void SetIcon( const wxString& iconFile, int iconIndex = 0 ) {
      m_iconFile = iconFile;
      m_iconIndex = iconIndex;
    }
    // set the short desc
    void SetShortDesc( const wxString& shortDesc ) { m_shortDesc = shortDesc; }

    // accessors
    // get the MIME type
    const wxString& GetMimeType() const { return m_mimeType; }
    // get the open command
    const wxString& GetOpenCommand() const { return m_openCmd; }
    // get the print command
    const wxString& GetPrintCommand() const { return m_printCmd; }
    // get the short description (only used under Win32 so far)
    const wxString& GetShortDesc() const { return m_shortDesc; }
    // get the long, user visible description
    const wxString& GetDescription() const { return m_desc; }
    // get the array of all extensions
    const wxArrayString& GetExtensions() const { return m_exts; }
    size_t GetExtensionsCount() const {return m_exts.GetCount(); }
    // get the icon info
    const wxString& GetIconFile() const { return m_iconFile; }
    int GetIconIndex() const { return m_iconIndex; }

  private:
    wxString m_mimeType,    // the MIME type in "type/subtype" form
             m_openCmd,     // command to use for opening the file (%s allowed)
             m_printCmd,    // command to use for printing the file (%s allowed)
             m_shortDesc,   // a short string used in the registry
             m_desc;        // a free form description of this file type

    // icon stuff
    wxString m_iconFile;    // the file containing the icon
    int      m_iconIndex;   // icon index in this file
    wxArrayString m_exts;   // the extensions which are mapped on this filetype

};

WX_DECLARE_USER_EXPORTED_OBJARRAY( wxFileTypeInfo, wxArrayFileTypeInfo);
class wxFileType {
    friend class wxMimeTypesManagerImpl;  // it has access to m_impl

  public:
    class MessageParameters {
      public:
        // ctors
        MessageParameters() { }
        MessageParameters( const wxString& filename,
                           const wxString& mimetype = wxEmptyString )
          : m_filename( filename ), m_mimetype( mimetype ) { }

        // accessors (called by GetOpenCommand)
        // filename
        const wxString& GetFileName() const { return m_filename; }
        // mime type
        const wxString& GetMimeType() const { return m_mimetype; }

        // override this function in derived class
        virtual wxString GetParamValue( const wxString& ( name ) ) const
        { return wxEmptyString; }

        // virtual dtor as in any base class
        virtual ~MessageParameters() { }

      protected:
        wxString m_filename, m_mimetype;
    };

    // ctor from static data
    wxFileType( const wxFileTypeInfo& ftInfo );

    // accessors: all of them return true if the corresponding information
    // could be retrieved/found, false otherwise (and in this case all [out]
    // parameters are unchanged)
    // return the MIME type for this file type
    bool GetMimeType( wxString *mimeType ) const;
    bool GetMimeTypes( wxArrayString& mimeTypes ) const;
    // fill passed in array with all extensions associated with this file
    // type
    bool GetExtensions( wxArrayString& extensions );
    // get the icon corresponding to this file type and of the given size
    bool GetIcon( wxIconLocation *iconloc ) const;
    bool GetIcon( wxIconLocation *iconloc,
                  const MessageParameters& params ) const;
    // get a brief file type description ("*.txt" => "text document")
    bool GetDescription( wxString *desc ) const;

    // get the command to be used to open/print the given file.
    // get the command to execute the file of given type
    bool GetOpenCommand( wxString *openCmd,
                         const MessageParameters& params ) const;
    // a simpler to use version of GetOpenCommand() -- it only takes the
    // filename and returns an empty string on failure
    wxString GetOpenCommand( const wxString& filename ) const;
    // get the command to print the file of given type
    bool GetPrintCommand( wxString *printCmd,
                          const MessageParameters& params ) const;


    // return the number of commands defined for this file type, 0 if none
    size_t GetAllCommands( wxArrayString *verbs, wxArrayString *commands,
                           const wxFileType::MessageParameters& params ) const;

    // set an arbitrary command, ask confirmation if it already exists and
    // overwriteprompt is true
    bool SetCommand( const wxString& cmd, const wxString& verb,
                     bool overwriteprompt = true );

    bool SetDefaultIcon( const wxString& cmd = wxEmptyString, int index = 0 );


    // remove the association for this filetype from the system MIME database:
    // notice that it will only work if the association is defined in the user
    // file/registry part, we will never modify the system-wide settings
    bool Unassociate();

    // operations
    // expand a string in the format of GetOpenCommand (which may contain
    // '%s' and '%t' format specificators for the file name and mime type
    // and %{param} constructions).
    static wxString ExpandCommand( const wxString& command,
                                   const MessageParameters& params );

    // dtor (not virtual, shouldn't be derived from)
    ~wxFileType();

  private:
    // default ctor is private because the user code never creates us
    wxFileType();

    // no copy ctor/assignment operator
    wxFileType( const wxFileType& );
    wxFileType& operator=( const wxFileType& );

    // the static container of wxFileType data: if it's not NULL, it means that
    // this object is used as fallback only
    const wxFileTypeInfo *m_info;

    // the object which implements the real stuff like reading and writing
    // to/from system MIME database
    wxFileTypeImpl *m_impl;
};

//----------------------------------------------------------------------------
// wxMimeTypesManagerFactory
//----------------------------------------------------------------------------

class wxMimeTypesManagerFactory {
  public:
    wxMimeTypesManagerFactory() {}
    virtual ~wxMimeTypesManagerFactory() {}

    virtual wxMimeTypesManagerImpl *CreateMimeTypesManagerImpl();

    static void Set( wxMimeTypesManagerFactory *factory );
    static wxMimeTypesManagerFactory *Get();

  private:
    static wxMimeTypesManagerFactory *m_factory;
};

// ----------------------------------------------------------------------------
// wxMimeTypesManager: interface to system MIME database.
//
// This class accesses the information about all known MIME types and allows
// the application to retrieve information (including how to handle data of
// given type) about them.
// ----------------------------------------------------------------------------

class wxMimeTypesManager {
  public:
    // static helper functions
    // -----------------------

    // check if the given MIME type is the same as the other one: the
    // second argument may contain wildcards ('*'), but not the first. If
    // the types are equal or if the mimeType matches wildcard the function
    // returns true, otherwise it returns false
    static bool IsOfType( const wxString& mimeType, const wxString& wildcard );

    // ctor
    wxMimeTypesManager();

    // NB: the following 2 functions are for Unix only and don't do anything
    //     elsewhere

    // loads data from standard files according to the mailcap styles
    // specified: this is a bitwise OR of wxMailcapStyle values
    //
    // use the extraDir parameter if you want to look for files in another
    // directory
    void Initialize( int mailcapStyle = wxMAILCAP_ALL,
                     const wxString& extraDir = wxEmptyString );

    // and this function clears all the data from the manager
    void ClearData();
    wxFileType *GetFileTypeFromExtension( const wxString& ext );
    // get file type from MIME type (in format <category>/<format>)
    wxFileType *GetFileTypeFromMimeType( const wxString& mimeType );
    bool ReadMailcap( const wxString& filename, bool fallback = false );
    // read in additional file in mime.types format
    bool ReadMimeTypes( const wxString& filename );

    // enumerate all known MIME types
    //
    // returns the number of retrieved file types
    size_t EnumAllFileTypes( wxArrayString& mimetypes );
    void AddFallbacks( const wxFileTypeInfo *filetypes );
    void AddFallback( const wxFileTypeInfo& ft ) { m_fallbacks.Add( ft ); }
    wxFileType *Associate( const wxFileTypeInfo& ftInfo );

    // undo Associate()
    bool Unassociate( wxFileType *ft ) ;

    // dtor (not virtual, shouldn't be derived from)
    ~wxMimeTypesManager();

  private:
    // no copy ctor/assignment operator
    wxMimeTypesManager( const wxMimeTypesManager& );
    wxMimeTypesManager& operator=( const wxMimeTypesManager& );
    wxArrayFileTypeInfo m_fallbacks;

    // the object working with the system MIME database
    wxMimeTypesManagerImpl *m_impl;

    // if m_impl is NULL, create one
    void EnsureImpl();

    friend class wxMimeTypeCmnModule;
};

extern wxMimeTypesManager * wxTheMimeTypesManager;

#endif // wxUSE_MIMETYPE

#endif
//_WX_MIMETYPE_H_
